// 基础发布者类：管理订阅者、提供“增删订阅者”和“通知”能力
class Publisher {
  constructor() {
    this.observers = []; // 存储订阅者列表
  }

  // 1. 添加订阅者（避免重复添加）
  add(observer) {
    if (!this.observers.includes(observer)) {
      this.observers.push(observer);
    }
  }

  // 2. 移除订阅者
  remove(observer) {
    this.observers = this.observers.filter(item => item !== observer);
  }

  // 3. 通知所有订阅者（传递自身，让订阅者获取最新状态）
  notify() {
    console.log(this);
    
    this.observers.forEach(observer => observer.update(this));
  }
}

// 基础观察者类：定义“接收通知”的统一接口（update方法）
class Observer {
  // 子类需重写此方法，实现具体响应逻辑
  update(publisher) {
    console.log('订阅者接收通知，待实现具体逻辑', publisher);
  }
}

// 具体发布者：需求文档管理器（维护需求状态）
class PrdPublisher extends Publisher {
  constructor() {
    super();
    this.prdState = null; // 需求文档状态（初始为空）
  }

  // 获取当前需求状态（给订阅者调用）
  getState() {
    return this.prdState;
  }

  // 更新需求状态（触发通知的核心方法）
  setState(newPrd) {
    this.prdState = newPrd; // 更新状态
    this.notify(); // 状态变了，立刻通知所有订阅者
  }
}

// 具体观察者：开发者（接收需求后开始工作）
class DeveloperObserver extends Observer {
  constructor(name) {
    super();
    this.name = name; // 开发者姓名（个性化标识）
    this.myPrd = null; // 本地存储接收的需求
  }

  // 重写update：接收需求并执行工作
  update(publisher) {
    this.myPrd = publisher.getState(); // 从发布者获取最新需求
    this.work(); // 执行具体工作
  }

  // 开发者的核心工作逻辑
  work() {
    console.log(`${this.name}：接收到需求《${this.myPrd.title}》，内容：${this.myPrd.content}，开始996开发！`);
  }
}

// 测试：模拟业务流程
const hanMeiMei = new PrdPublisher(); // 发布者：韩梅梅（产品）
const liLei = new DeveloperObserver('李雷（前端）'); // 订阅者1：前端
const wangWu = new DeveloperObserver('王五（后端）'); // 订阅者2：后端

// 1. 拉群（添加订阅者）
hanMeiMei.add(liLei);
hanMeiMei.add(wangWu);

// 2. 发布需求（更新状态，触发通知）
hanMeiMei.setState({
  title: '员工管理系统V2.0',
  content: '新增考勤打卡、请假审批模块'
});

// 输出结果：
// 李雷（前端）：接收到需求《员工管理系统V2.0》，内容：新增考勤打卡、请假审批模块，开始996开发！
// 王五（后端）：接收到需求《员工管理系统V2.0》，内容：新增考勤打卡、请假审批模块，开始996开发！